package com.ruoyi.system.service.impl;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

import com.ruoyi.common.constant.CarConstans;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.SysCarStateInfoMapper;

/**
 * 车况信息Service业务层处理
 *
 * @author ruoyi
 * @date 2022-05-11
 */
@Service
public class SysCarStateInfoServiceImpl implements ISysCarStateInfoService {
    @Autowired
    private SysCarStateInfoMapper sysCarStateInfoMapper;

    @Autowired
    private ISysConfigErrorService sysConfigErrorService;

    @Autowired
    private ISysErrorConditionsService sysErrorConditionsService;

    @Autowired
    private ISysCarResultsService sysCarResultsService;

    @Autowired
    private ISysAlarmsService sysAlarmsService;

    /**
     * 查询车况信息
     *
     * @param infoId 车况信息主键
     * @return 车况信息
     */
    @Override
    public SysCarStateInfo selectSysCarStateInfoByInfoId(Long infoId) {
        return sysCarStateInfoMapper.selectSysCarStateInfoByInfoId(infoId);
    }

    /**
     * 查询车况信息列表
     *
     * @param sysCarStateInfo 车况信息
     * @return 车况信息
     */
    @Override
    public List<SysCarStateInfo> selectSysCarStateInfoList(SysCarStateInfo sysCarStateInfo) {
        return sysCarStateInfoMapper.selectSysCarStateInfoList(sysCarStateInfo);
    }

    /**
     * 新增车况信息
     *
     * @param sysCarStateInfo 车况信息
     * @return 结果
     */
    @Override
    public int insertSysCarStateInfo(SysCarStateInfo sysCarStateInfo) {
        if (sysCarStateInfo == null) return -1;
        return sysCarStateInfoMapper.insertSysCarStateInfo(sysCarStateInfo);
    }

    public int check(SysCarStateInfo sysCarStateInfo) {
        //检测是否有故障
        return testSysCarStateInfo(sysCarStateInfo);
    }
    public int testSysCarStateInfo(SysCarStateInfo sysCarStateInfo) {
        //如果故障码不为空则直接查询
        String errorCode = sysCarStateInfo.getErrorCode();
        if (errorCode != null && errorCode.length() != 0) {
            String[] errorCodeList = errorCode.split(",");
            if (errorCodeList.length == 0) return -1;
            List<SysErrorConditions> errorConditionsList = sysErrorConditionsService.selectConditionsListByErrorCodes(errorCodeList);
            //直接构造故障信息
            return buildErrorInfo(errorConditionsList, sysCarStateInfo);
        } else {
            //构造错误信息和报警信息
            Map<String, Object> map = null;
            try {
                map = buildFieldMap(sysCarStateInfo);
            } catch (IllegalAccessException e) {
            }
            //可以创建为异步逻辑
            List<SysErrorConditions> errorConditionsList = buildErrorResult(map, sysCarStateInfo);
            return buildErrorInfo(errorConditionsList, sysCarStateInfo);
        }
    }

    private List<SysErrorConditions> buildErrorResult(Map<String, Object> map, SysCarStateInfo sysCarStateInfo) {
        List<SysConfigError> sysConfigErrors = sysConfigErrorService.selectSysConfigErrorList(null);
        if (sysConfigErrors == null || sysConfigErrors.size() == 0) return null;
        //获取所有故障类型
        List<Long> errorIds = sysConfigErrors.stream().map(SysConfigError::getErrorId).collect(Collectors.toList());
        List<SysErrorConditions> resList = new ArrayList<>();
        for (Long errorId : errorIds) {
            SysErrorConditions sysErrorConditions = new SysErrorConditions();
            sysErrorConditions.setErrorId(errorId);
            //查询该故障的所有条件
            List<SysErrorConditions> conditionList = sysErrorConditionsService.selectSysErrorConditionsList(sysErrorConditions);
            //构造异常信息
            List<SysErrorConditions> judgedErrorList = getConditions(conditionList, map);
            //将异常汇总
            if (judgedErrorList.size() > 0) resList.addAll(judgedErrorList);
        }
        return resList;
    }

    private int buildErrorInfo(List<SysErrorConditions> conditionList, SysCarStateInfo sysCarStateInfo) {
        SysCarResults sysCarResults = new SysCarResults();
        sysCarResults.setErrorNum((long) conditionList.size());
        sysCarResults.setCreateAt(new Date());
        sysCarResults.setStateInfoId(sysCarStateInfo.getInfoId());
        sysCarResults.setErrorInfo(generateErrorInfo(conditionList));
        //插入结果信息
        int row = 0;
        row += sysCarResultsService.insertSysCarResults(sysCarResults);
        //生成报警记录
        if (conditionList.size() > 0) row += sysAlarmsService.insertSysAlarms(buildAlaramByCarResults(sysCarResults, sysCarStateInfo.getCarId()));
        return row;
    }

    private SysAlarms buildAlaramByCarResults(SysCarResults sysCarResults, Long carId) {
        SysAlarms sysAlarms = new SysAlarms();
        sysAlarms.setAlarmInfo(sysCarResults.getErrorInfo());
        sysAlarms.setCreateAt(new Date());
        sysAlarms.setCarId(carId);
        //
        sysAlarms.setResId(sysCarResults.getResId());
        return sysAlarms;
    }

    private String generateErrorInfo(List<SysErrorConditions> conditionList) {
        if (conditionList == null || conditionList.size() == 0) return "无故障";
        //以  (i)故障信息：XXXX；
        //      故障原因：XXXX；形式构造
        StringBuilder sb = new StringBuilder();
        int n = conditionList.size();
        for (int i = 0; i < n; i++) {
            SysErrorConditions con = conditionList.get(i);
            sb.append("(").append(i + 1).append(")");
            //获取error配置
            SysConfigError error = sysConfigErrorService.selectSysConfigErrorByErrorId(con.getErrorId());
            sb.append("故障位置:").append(error.getName()).append("-").append(error.getLocation()).append("\n");
            sb.append("   ").append("故障信息:").append(con.getErrorInfo()).append("\n");
            sb.append("   ").append("故障可能原因:").append(con.getErrorReason());
            if (i != n - 1) sb.append("\n");
        }
        return sb.toString();
    }

    //条件判断
    private List<SysErrorConditions> getConditions(List<SysErrorConditions> conditions, Map<String, Object> map) {
        //分出条件
        List<SysErrorConditions> preCons = conditions.stream().filter(con -> CarConstans.CON_TYPE_PRE.equals(con.getConType())).collect(Collectors.toList());
        List<SysErrorConditions> res = new ArrayList<>();
        //没有先决条件
        if (preCons.size() == 0) {
            //这里规定一个judge条件一定有一个故障信息
            //构建最终错误列表
            //由于preConditions为0,所以直接赋值即可
            judgeConditions(conditions, map, res);
        }
        //判断先决条件
        else if (judgeConditions(preCons, map, null)) {
            //这里规定一个judge条件一定有一个故障信息
            List<SysErrorConditions> judgeCons = conditions.stream().filter(con -> CarConstans.CON_TYPE_JUDGE.equals(con.getConType())).collect(Collectors.toList());
            //构建最终错误列表
            judgeConditions(judgeCons, map, res);
        }
        return res;
    }

    private boolean judgeConditions(List<SysErrorConditions> cons, Map<String, Object> map, List<SysErrorConditions> res) {
        for (SysErrorConditions con : cons) {
            //不满足条件直接返回
            if (!operate(con, map)) return false;
            else {
                if (res != null) res.add(con);
            }
        }
        return true;
    }

    private boolean operate(SysErrorConditions preCon, Map<String, Object> map) {
        boolean res = true;
        String field1 = preCon.getField1();
        String field2 = preCon.getField2();
        Object value1 = null;
        Object value2 = null;
        boolean solve1 = false;
        boolean solve2 = false;
        HashSet<String> set = new HashSet() {{
            add("+");
            add("-");
            add("*");
            add("/");
        }};
        if (field1 != null && !"".equals(field1)) {
            value1 = map.get(field1);
            if ("null".equals(preCon.getOperation1())) {
                if (value1 != null) return false;
                solve1 = true;
            }
            else if (value1 == null) return false;
        }
        if (field2 != null && !"".equals(field2)) {
            value2 = map.get(field2);
            if ("null".equals(preCon.getOperation2())) {
                if (value2 != null) return false;
                solve2 = true;
            }
            else if (value2 == null) return false;
        }
        if (set.contains(preCon.getOperation1())) {
            if (value2 == null) return false;
            res = operateHelp(parse(value1), parse(value2), preCon.getOperation1(), preCon.getValue1().doubleValue(), preCon.getOperation2());
        } else {
            //判断两个条件
            if (!solve1 && !"".equals(field1))
                res = operateHelp(parse(value1), preCon.getValue1().doubleValue(), preCon.getOperation1());
            if (!solve2 && !"".equals(field2))
                res = res && operateHelp(parse(value2), preCon.getValue2().doubleValue(), preCon.getOperation2());
        }
        return res;
    }

    private Double parse(Object value) {
        if (value instanceof Date) {
            return Double.parseDouble(Long.toString(((Date)value).getTime()));
        }
        return Double.parseDouble(value.toString());
    }

    private boolean operateHelp(Double value1, Double value2, String oper) {

        switch (oper) {
            case "null":
                return value1 == null;
            case "0":
                return value1.equals(value2);
            case "1":
                return value1 > value2;
            case "2":
                return value1 < value2;
            case "3":
                return value1 >= value2;
            case "4":
                return value1 <= value2;
            default:
                return false;
        }
    }

    private boolean operateHelp(Double value1, Double value2, String oper1, Double value3, String oper2) {
        switch (oper1) {
            case "+":
                return operateHelp(value1 + value2, value3, oper2);
            case "-":
                return operateHelp(value1 - value2, value3, oper2);
            case "*":
                return operateHelp(value1 * value2, value3, oper2);
            case "/":
                if (value2 != 0.0) return operateHelp(value1 / value2, value3, oper2);
                else return false;
            default:
                return false;
        }
    }

    //构建成map
    private Map<String, Object> buildFieldMap(SysCarStateInfo sysCarStateInfo) throws IllegalAccessException {

        HashMap<String, Object> map = new HashMap<>();

        Field[] fields = sysCarStateInfo.getClass().getDeclaredFields();

        for (int i = 4, len = fields.length; i < len; i++) {

            String varName = fields[i].getName();

            boolean accessFlag = fields[i].isAccessible();

            fields[i].setAccessible(true);

            Object o = fields[i].get(sysCarStateInfo);

            map.put(varName, o);

            fields[i].setAccessible(accessFlag);
        }
        return map;
    }

    /**
     * 修改车况信息
     *
     * @param sysCarStateInfo 车况信息
     * @return 结果
     */
    @Override
    public int updateSysCarStateInfo(SysCarStateInfo sysCarStateInfo) {
        return sysCarStateInfoMapper.updateSysCarStateInfo(sysCarStateInfo);
    }

    /**
     * 批量删除车况信息
     *
     * @param infoIds 需要删除的车况信息主键
     * @return 结果
     */
    @Override
    public int deleteSysCarStateInfoByInfoIds(Long[] infoIds) {
        return sysCarStateInfoMapper.deleteSysCarStateInfoByInfoIds(infoIds);
    }

    /**
     * 删除车况信息信息
     *
     * @param infoId 车况信息主键
     * @return 结果
     */
    @Override
    public int deleteSysCarStateInfoByInfoId(Long infoId) {
        return sysCarStateInfoMapper.deleteSysCarStateInfoByInfoId(infoId);
    }
}
